#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <strings.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>     /*包含close函数，关闭套接字文件描述符*/


#define RECVBUFFERSIZE  2048
#define PORTNUMBER      8888

void *rec_func(void *arg)
{
    int new_fd;
    char buffer[RECVBUFFERSIZE];
    int nbytes;

    new_fd = *((int *)arg);

    /*释放在主线程中分配的空间*/
    free(arg);

    /*循环接收客户端发送来的数据，并将信息放松回去*/
    while(1)
    {
        nbytes = recv(new_fd, buffer, RECVBUFFERSIZE, 0);
        if(nbytes == -1)
        {
            printf("Read error: %s\n", strerror(errno));
            close(new_fd);
            return (void *)-1;
        }
        if(nbytes == 0)
        {
            /*客户端主动断开连接，返回值是0*/
            close(new_fd);
            break;
        }
        /*接收到了正常的字符*/
        buffer[nbytes] = '\0';
        printf("I have received: %s\n", buffer);

        /*向客户端发送信息*/
        if(send(new_fd, buffer, strlen(buffer), 0) == -1)
        {
            printf("Send error: %s\n", strerror(errno));
            close(new_fd);
            return (void *)-1;
        }
    }

    return (void *)0;
    
}


int main(int argc, char **argv)
{
    int sockfd, new_fd;
    unsigned int sin_size;
    int *pconnsock = NULL;
    int ret;
    pthread_t tid;

    struct sockaddr_in server_addr;     /*struct sockaddr_in是在头文件<arpa/inet.h>中定义*/
    struct sockaddr_in client_addr;

    /*服务器端开始建立socket描述符  sockfd用于监听*/
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd == -1)
    {
        printf("socket establish error\n");
        return -1;
    }

    /*服务器端填充sockaddr结构*/
    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);    /*自动获取网卡地址*/
    server_addr.sin_port = htons(PORTNUMBER);

    /*绑定socket描述符*/
    if(bind(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1)
    {
        printf("bind error\n");
        return -1;
    }

    /*监听sockfd描述符*/
    if(listen(sockfd, 10) == -1)
    {
        printf("listen error\n");
        return -1;
    }
    sin_size = sizeof(struct sockaddr);
    /*循环接收客户端的连接*/
    while(1)
    {
        /*accept函数的将阻塞的接收客户端的连接*/
        new_fd = accept(sockfd, (struct sockaddr *)(&client_addr), &sin_size);
        if(new_fd == -1)
        {
            printf("accept error\n");
            return -1;
        }

        /*利用malloc函数分配new_fd的位置，防止在thread1处理线程中，
         *未及时取走new_fd的而导致主线程又再一次覆盖了new_fd的值，
         *因为传递给pthread_create函数的参数是指针，每一个线程得到的
         *new_fd地址都是一样的*/
         /*采用堆内存的方式，避免传递同一个地址*/
        pconnsock = (int *)malloc(sizeof(int));
        *pconnsock = new_fd;
        /*为每一个客户端连接创建一个线程进行处理*/
        ret = pthread_create(&tid, NULL, rec_func, (void *)pconnsock);
        if(ret != 0)
        {
            perror("pthread_create");
            return -1;
        }
    }

    close(sockfd);

    return 0;
}















